import 'package:eplorex/models/send_button_visibility_mode.dart';
import 'package:eplorex/pages/message/state/inherited_l10n.dart';
import 'package:eplorex/widgets/input/voice_input.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:eplorex/models/message/chat_message_type.dart' as types;

import '../../models/input_clear_mode.dart';
import '../../pages/message/chat/chat_util.dart';
import '../../pages/message/state/inherited_chat_theme.dart';
import 'attachment_button.dart';
import 'chat_add_view.dart';
import 'input_text_field_controller.dart';
import 'send_button.dart';

/// A class that represents bottom bar widget with a text field, attachment and
/// send buttons inside. By default hides send button when text field is empty.
class Input extends StatefulWidget {
  /// Creates [Input] widget.
  const Input({
    super.key,
    this.isAttachmentUploading,
    this.onAttachmentPressed,
    this.onVoicePressed,
    this.backgroundTap,
    required this.onSendPressed,
    this.options = const InputOptions(),
  });

  /// Whether attachment is uploading. Will replace attachment button with a
  /// [CircularProgressIndicator]. Since we don't have libraries for
  /// managing media in dependencies we have no way of knowing if
  /// something is uploading so you need to set this manually.
  final bool? isAttachmentUploading;

  /// See [AttachmentButton.onPressed].
  final VoidCallback? onAttachmentPressed;

  /// See
  final ValueNotifier<bool>? backgroundTap;

  /// See [VoiceButton.onPressed].
  final VoidCallback? onVoicePressed;

  /// Will be called on [SendButton] tap. Has [types.PartialText] which can
  /// be transformed to [types.TextMessage] and added to the messages list.
  final void Function(types.PartialText) onSendPressed;

  /// Customisation options for the [Input].
  final InputOptions options;

  @override
  State<Input> createState() => _InputState();
}

/// [Input] widget state.
class _InputState extends State<Input> {
  late final _inputFocusNode = FocusNode(
    onKeyEvent: (node, event) {
      if (event.physicalKey == PhysicalKeyboardKey.enter &&
          !HardwareKeyboard.instance.physicalKeysPressed.any(
            (el) => <PhysicalKeyboardKey>{
              PhysicalKeyboardKey.shiftLeft,
              PhysicalKeyboardKey.shiftRight,
            }.contains(el),
          )) {
        if (kIsWeb && _textController.value.isComposingRangeValid) {
          return KeyEventResult.ignored;
        }
        if (event is KeyDownEvent) {
          _handleSendPressed();
        }
        return KeyEventResult.handled;
      } else {
        return KeyEventResult.ignored;
      }
    },
  );

  bool _sendButtonVisible = false;
  late TextEditingController _textController;
  bool _hideAddView = true;

  @override
  void initState() {
    super.initState();

    _textController =
        widget.options.textEditingController ?? InputTextFieldController();
    _handleSendButtonVisibilityModeChange();
    _inputFocusNode.addListener(() {
     if( (_inputFocusNode.hasFocus)){
       if(!_hideAddView){
         setState(() {
           _hideAddView=!_hideAddView;
         });
       }
     }
    });
    widget.backgroundTap!.addListener(_handleBackgroundTap);
  }

  void _handleBackgroundTap(){
    if(!_hideAddView){
      setState(() {
        _hideAddView=!_hideAddView;
      });
    }
  }

  void _handleSendButtonVisibilityModeChange() {
    _textController.removeListener(_handleTextControllerChange);
    if (widget.options.sendButtonVisibilityMode ==
        SendButtonVisibilityMode.hidden) {
      _sendButtonVisible = false;
    } else if (widget.options.sendButtonVisibilityMode ==
        SendButtonVisibilityMode.editing) {
      _sendButtonVisible = _textController.text.trim() != '';
      _textController.addListener(_handleTextControllerChange);
    } else {
      _sendButtonVisible = true;
    }
  }

  void _handleSendPressed() {
    final trimmedText = _textController.text.trim();
    if (trimmedText != '') {
      final partialText = types.PartialText(text: trimmedText);
      widget.onSendPressed(partialText);

      if (widget.options.inputClearMode == InputClearMode.always) {
        _textController.clear();
      }
    }
  }

  void _handleTextControllerChange() {
    if (_textController.value.isComposingRangeValid) {
      return;
    }
    setState(() {
      _sendButtonVisible = _textController.text.trim() != '';
    });
  }

  Widget _inputBuilder() {
    final query = MediaQuery.of(context);
    final buttonPadding = InheritedChatTheme.of(context)
        .theme
        .inputPadding
        .copyWith(left: 16, right: 16);
    final safeAreaInsets = isMobile
        ? EdgeInsets.fromLTRB(
            query.padding.left,
            0,
            query.padding.right,
            query.viewInsets.bottom + query.padding.bottom - 20,
          )
        : EdgeInsets.zero;
    final textPadding = InheritedChatTheme.of(context)
        .theme
        .inputPadding
        .copyWith(left: 0, right: 0)
        .add(
          EdgeInsets.fromLTRB(
            widget.onAttachmentPressed != null ? 0 : 24,
            0,
            _sendButtonVisible ? 0 : 24,
            0,
          ),
        );

    return Focus(
      autofocus: !widget.options.autofocus,
      child: Padding(
        padding: InheritedChatTheme.of(context).theme.inputMargin,
        child: Material(
          // borderRadius: InheritedChatTheme.of(context).theme.inputBorderRadius,
          color: InheritedChatTheme.of(context).theme.inputBackgroundColor,
          surfaceTintColor:
              InheritedChatTheme.of(context).theme.inputSurfaceTintColor,
          elevation: InheritedChatTheme.of(context).theme.inputElevation,
          child: Container(
            decoration:
                InheritedChatTheme.of(context).theme.inputContainerDecoration,
            padding: safeAreaInsets,
            child: Column(
              children: [
                Container(
                  child: Row(
                    textDirection: TextDirection.ltr,
                    children: [
                      VoiceButton(
                        onPressed: widget.onVoicePressed,
                      ),
                      Expanded(
                        child: Padding(
                          padding: textPadding,
                          child: TextField(
                            enabled: widget.options.enabled,
                            autocorrect: widget.options.autocorrect,
                            autofocus: widget.options.autofocus,
                            enableSuggestions: widget.options.enableSuggestions,
                            controller: _textController,
                            cursorColor: InheritedChatTheme.of(context)
                                .theme
                                .inputTextCursorColor,
                            decoration: InheritedChatTheme.of(context)
                                .theme
                                .inputTextDecoration
                                .copyWith(
                                  hintStyle: InheritedChatTheme.of(context)
                                      .theme
                                      .inputTextStyle
                                      .copyWith(
                                        color: InheritedChatTheme.of(context)
                                            .theme
                                            .inputTextColor
                                            .withOpacity(0.5),
                                      ),
                                  hintText: InheritedL10n.of(context)
                                      .l10n
                                      .inputPlaceholder,
                                ),
                            focusNode: _inputFocusNode,
                            keyboardType: widget.options.keyboardType,
                            maxLines: 5,
                            minLines: 1,
                            onChanged: widget.options.onTextChanged,
                            onTap: widget.options.onTextFieldTap,
                            style: InheritedChatTheme.of(context)
                                .theme
                                .inputTextStyle
                                .copyWith(
                                  color: InheritedChatTheme.of(context)
                                      .theme
                                      .inputTextColor,
                                ),
                            textCapitalization: TextCapitalization.sentences,
                          ),
                        ),
                      ),
                      if (widget.onAttachmentPressed != null)
                        AttachmentButton(
                          isLoading: widget.isAttachmentUploading ?? false,
                          onPressed: () {
                            _inputFocusNode.unfocus();
                            setState(() {
                              _hideAddView = !_hideAddView;
                            });
                          },
                          padding: buttonPadding,
                        ),
                      ConstrainedBox(
                        constraints: BoxConstraints(
                          minHeight:
                              buttonPadding.bottom + buttonPadding.top + 24,
                        ),
                        child: Visibility(
                          visible: _sendButtonVisible,
                          child: SendButton(
                            onPressed: _handleSendPressed,
                            padding: buttonPadding,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
                Offstage(
                  offstage: _hideAddView,
                  child: ChatAddView(
                    viewType: 1,
                    toChatId: "widget.toChatId",
                    refreshMediaCallback:
                        (type, mediaURL, thumbnailFileName, second, messageId) {
                      // _refreshMedia(type, mediaURL, thumbnailFileName, mediaSecond: second , messageId: messageId);
                    },
                    sendMedialCallback: (type, mediaURL, messageId) {
                      print("sendMedialCallback called");
                      setState(() {
                        _hideAddView=true;
                      });
                      // _sendMedia(type, mediaURL, mediaSecond: second, messageId: messageId);
                    },
                    refreshRedpacketAndTransfer: null,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  @override
  void didUpdateWidget(covariant Input oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.options.sendButtonVisibilityMode !=
        oldWidget.options.sendButtonVisibilityMode) {
      _handleSendButtonVisibilityModeChange();
    }
  }

  @override
  void dispose() {
    _inputFocusNode.dispose();
    _textController.dispose();
    widget.backgroundTap?.removeListener(_handleBackgroundTap);

    super.dispose();
  }

  @override
  Widget build(BuildContext context) => GestureDetector(
        onTap: () {
          _inputFocusNode.requestFocus();
        },
        child: _inputBuilder(),
      );
}

@immutable
class InputOptions {
  const InputOptions({
    this.inputClearMode = InputClearMode.always,
    this.keyboardType = TextInputType.multiline,
    this.onTextChanged,
    this.onTextFieldTap,
    this.sendButtonVisibilityMode = SendButtonVisibilityMode.editing,
    this.textEditingController,
    this.autocorrect = true,
    this.autofocus = false,
    this.enableSuggestions = true,
    this.enabled = true,
  });

  /// Controls the [Input] clear behavior. Defaults to [InputClearMode.always].
  final InputClearMode inputClearMode;

  /// Controls the [Input] keyboard type. Defaults to [TextInputType.multiline].
  final TextInputType keyboardType;

  /// Will be called whenever the text inside [TextField] changes.
  final void Function(String)? onTextChanged;

  /// Will be called on [TextField] tap.
  final VoidCallback? onTextFieldTap;

  /// Controls the visibility behavior of the [SendButton] based on the
  /// [TextField] state inside the [Input] widget.
  /// Defaults to [SendButtonVisibilityMode.editing].
  final SendButtonVisibilityMode sendButtonVisibilityMode;

  /// Custom [TextEditingController]. If not provided, defaults to the
  /// [InputTextFieldController], which extends [TextEditingController] and has
  /// additional fatures like markdown support. If you want to keep additional
  /// features but still need some methods from the default [TextEditingController],
  /// you can create your own [InputTextFieldController] (imported from this lib)
  /// and pass it here.
  final TextEditingController? textEditingController;

  /// Controls the [TextInput] autocorrect behavior. Defaults to [true].
  final bool autocorrect;

  /// Whether [TextInput] should have focus. Defaults to [false].
  final bool autofocus;

  /// Controls the [TextInput] enableSuggestions behavior. Defaults to [true].
  final bool enableSuggestions;

  /// Controls the [TextInput] enabled behavior. Defaults to [true].
  final bool enabled;
}
